package com.hawthorn.admin.service.sysrole.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hawthorn.admin.feign.redisService.RedisRoleFeignService;
import com.hawthorn.admin.repository.SysRoleMapper;
import com.hawthorn.admin.repository.SysRoleMenuMapper;
import com.hawthorn.admin.service.sysrole.SysRoleService;
import com.hawthorn.component.constant.RedisConstant;
import com.hawthorn.component.utils.bean.Map2ObjUtil;
import com.hawthorn.entity.po.SysRoleMenuPO;
import com.hawthorn.entity.po.SysRolePO;
import com.hawthorn.platform.exception.BizCode;
import com.hawthorn.platform.redis.RedisMyClient;
import com.hawthorn.platform.service.TransResultService;
import com.hawthorn.platform.utils.common.MyUtil;
import com.hawthorn.platform.utils.common.StrMyUtil;
import com.hawthorn.platform.utils.iassert.AssertMyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>todo 系统角色service</p>
 * @author: andy.ten@tom.com | xukaixing@hotmail.com
 * @created: 2022/7/29 10:28
 * @version v1.0.1
 * @copyright: Copyright (c)  andyten
 */
@Service
@Slf4j
public class SysRoleServiceImpl implements SysRoleService
{
  @Resource
  private SysRoleMapper sysRoleMapper;

  @Resource
  private SysRoleMenuMapper sysRoleMenuMapper;

  @Resource
  private TransResultService transResultService;

  @Resource
  private RedisMyClient redisMyClient;

  @Resource
  private RedisRoleFeignService redisRoleFeignService;

  private HashMap<String, String> getTransHash()
  {
    HashMap<String, String> transHash = new HashMap<>();
    transHash.put("level", "dic|zzjb");
    transHash.put("status", "dic|yxzt");
    transHash.put("deptId", "dept|o");

    return transHash;
  }

  /**
   * <p>todo 查询角色信息</p>
   * @param: page
   * @param: conditions
   * @return: com.baomidou.mybatisplus.core.metadata.IPage<java.util.Map < java.lang.String, java.lang.Object>>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/29 10:29
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/29    andy.ten        v1.0.1             init
   */
  @Override
  public IPage<Map<String, Object>> findRoles(Page<Map<String, Object>> page, String conditions)
  {

    // 设置排序
    OrderItem oi = new OrderItem();
    oi.setColumn("createTime");
    oi.setAsc(false);
    List<OrderItem> al = page.getOrders();
    al.add(oi);
    page.setOrders(al);
    return transResultService.transResult(sysRoleMapper.findRoles(page, conditions), getTransHash());
  }

  /**
   * <p>todo 查询渠道角色信息</p>
   * @param: page
   * @param: conditions
   * @return: com.baomidou.mybatisplus.core.metadata.IPage<java.util.Map < java.lang.String, java.lang.Object>>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/29 10:29
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/29    andy.ten        v1.0.1             init
   */
  @Override
  public IPage<Map<String, Object>> findDealerRoles(Page<Map<String, Object>> page, String conditions)
  {
    // 设置排序
    OrderItem oi = new OrderItem();
    oi.setColumn("createTime");
    oi.setAsc(false);
    List<OrderItem> al = page.getOrders();
    al.add(oi);
    page.setOrders(al);
    return transResultService.transResult(sysRoleMapper.findDealerRoles(page, conditions), getTransHash());
  }

  /**
   * <p>todo 新增角色</p>
   * @param: param
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/29 14:11
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/29    andy.ten        v1.0.1             init
   */
  @Override
  public Map<String, Object> saveRole(Map<String, Object> param)
  {
    SysRolePO sysRolePO = Map2ObjUtil.toObject(param, SysRolePO.class);
    AssertMyUtil.notNull(sysRolePO, BizCode.VARIABLE_NOT_NULL, "sysRolePO");
    // 判断角色代码是否已存在
    Integer roleIsExist = sysRoleMapper.findRoleByCode(sysRolePO.getRcode());
    if (roleIsExist != 0)
    {
      AssertMyUtil.errMsg("角色代码已存在.");
    }

    // 设置company、oemCompany
    if (sysRolePO.getDeptId() != null)
    {
      Map deptInfo = redisMyClient.getDeptInfo(sysRolePO.getDeptId());
      sysRolePO.setCompanyId(Long.valueOf(MyUtil.getValue(deptInfo.get("companyId"))));
      sysRolePO.setOemCompanyId(Long.valueOf(MyUtil.getValue(deptInfo.get("oemCompanyId"))));
    }
    sysRoleMapper.save(sysRolePO);

    // todo: 同步到redis
    redisRoleFeignService.saveRole(sysRolePO);

    return transResultService.transResult(sysRolePO.toMaps(), getTransHash());
  }

  /**
   * <p>todo 渠道商新增角色</p>
   * @param: param
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2023/2/20 14:56
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2023/2/20    andy.ten        v1.0.1             init
   */
  @Override
  public Map<String, Object> saveDealerRole(Map<String, Object> param)
  {
    SysRolePO sysRolePO = Map2ObjUtil.toObject(param, SysRolePO.class);
    AssertMyUtil.notNull(sysRolePO, BizCode.VARIABLE_NOT_NULL, "sysRolePO");
    // 判断角色代码是否已存在
    Integer roleIsExist = sysRoleMapper.findDealerRoleByCode(sysRolePO.getRcode(), sysRolePO.getDeptId());
    if (roleIsExist != 0)
    {
      AssertMyUtil.errMsg("角色代码已存在.");
    }

    // 设置company、oemCompany
    if (sysRolePO.getDeptId() != null)
    {
      Map deptInfo = redisMyClient.getDeptInfo(sysRolePO.getDeptId());
      sysRolePO.setCompanyId(Long.valueOf(MyUtil.getValue(deptInfo.get("companyId"))));
      sysRolePO.setOemCompanyId(Long.valueOf(MyUtil.getValue(deptInfo.get("oemCompanyId"))));
    }
    sysRoleMapper.save(sysRolePO);

    // todo: 同步到redis
    redisRoleFeignService.saveRole(sysRolePO);

    return transResultService.transResult(sysRolePO.toMaps(), getTransHash());
  }

  /**
   * <p>todo 更新角色</p>
   * @param: id
   * @param: param
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/29 14:12
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/29    andy.ten        v1.0.1             init
   */
  @Override
  public Map<String, Object> updateRole(Long id, Map<String, Object> param)
  {
    AssertMyUtil.notNull(id, BizCode.METHOD_ARGS_NOTNULL, "id");
    SysRolePO sysRolePO = sysRoleMapper.selectById(id);
    String oriRoleCode = sysRolePO.getRcode();
    Map2ObjUtil.toObject(param, sysRolePO);
    String newRoleCode = sysRolePO.getRcode();

    // 判断角色代码是否已存在
    if (!oriRoleCode.equals(newRoleCode))
    {
      Integer roleIsExist = sysRoleMapper.findDealerRoleByCode(newRoleCode, sysRolePO.getDeptId());
      if (roleIsExist != 0)
      {
        AssertMyUtil.errMsg("角色代码已存在.");
      }
    }


    // 设置company、oemCompany
    if (sysRolePO.getDeptId() != null)
    {
      Map deptInfo = redisMyClient.getDeptInfo(sysRolePO.getDeptId());
      sysRolePO.setCompanyId(Long.valueOf(MyUtil.getValue(deptInfo.get("companyId"))));
      sysRolePO.setOemCompanyId(Long.valueOf(MyUtil.getValue(deptInfo.get("oemCompanyId"))));
    }

    sysRoleMapper.updateById(sysRolePO);

    // todo: 同步到redis
    redisRoleFeignService.updateRole(sysRolePO);

    return transResultService.transResult(sysRolePO.toMaps(), getTransHash());
  }

  /**
   * <p>todo 更新渠道商角色</p>
   * @param: id
   * @param: param
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/29 14:12
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/29    andy.ten        v1.0.1             init
   */
  @Override
  public Map<String, Object> updateDealerRole(Long id, Map<String, Object> param)
  {
    AssertMyUtil.notNull(id, BizCode.METHOD_ARGS_NOTNULL, "id");
    SysRolePO sysRolePO = sysRoleMapper.selectById(id);
    String oriRoleCode = sysRolePO.getRcode();
    Map2ObjUtil.toObject(param, sysRolePO);
    String newRoleCode = sysRolePO.getRcode();

    // 判断角色代码是否已存在
    if (!oriRoleCode.equals(newRoleCode))
    {
      Integer roleIsExist = sysRoleMapper.findDealerRoleByCode(newRoleCode, sysRolePO.getDeptId());
      if (roleIsExist != 0)
      {
        AssertMyUtil.errMsg("角色代码已存在.");
      }
    }

    sysRoleMapper.updateById(sysRolePO);

    // todo: 同步到redis
    redisRoleFeignService.updateRole(sysRolePO);

    return transResultService.transResult(sysRolePO.toMaps(), getTransHash());
  }

  /**
   * <p>todo 修改角色状态</p>
   * @param: id
   * @param: status
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/29 14:15
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/29    andy.ten        v1.0.1             init
   */
  @Override
  public Map<String, Object> updateRoleStatus(Long id, Integer status)
  {
    SysRolePO sysRolePO = sysRoleMapper.selectById(id);
    UpdateWrapper<SysRolePO> uw = new UpdateWrapper<>();
    uw.set("status", status);
    uw.eq("id", id);
    sysRoleMapper.update(sysRolePO, uw);

    // todo: 同步到redis
    redisRoleFeignService.updateRole(sysRolePO);

    return sysRolePO.toMaps();
  }

  /**
   * <p>todo 授予角色菜单权限</p>
   * @param: params
   * @return: void
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/30 16:52
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/30    andy.ten        v1.0.1             init
   */
  @Override
  public void saveAuthGrantMenus(List<Map<String, Object>> params)
  {
    // todo 删除原授权信息
    Long roleId = Long.valueOf(MyUtil.getValue(params.get(0).get("roleId")));
    LambdaQueryWrapper<SysRoleMenuPO> lambdaQuery = Wrappers.lambdaQuery();
    lambdaQuery.eq(SysRoleMenuPO::getRoleId, roleId);
    sysRoleMenuMapper.remove(lambdaQuery);
    // todo 插入新授权
    params.forEach(grant ->
    {
      SysRoleMenuPO sysRoleMenuPO = new SysRoleMenuPO();
      sysRoleMenuPO.setRoleId(Long.valueOf(MyUtil.getValue(grant.get("roleId"))));
      sysRoleMenuPO.setMenuId(Long.valueOf(MyUtil.getValue(grant.get("menuId"))));
      sysRoleMenuPO.setPerms(MyUtil.getValue(grant.get("perms")));
      sysRoleMenuMapper.save(sysRoleMenuPO);
    });
    // todo 查询该角色下的全部用户并删除用户已加载的用户授权缓存
    List<Map<String, Object>> userList = sysRoleMapper.findUserByRoleId(roleId);
    userList.forEach(user ->
    {
      String roleMenuKey = StrMyUtil.placeHolder(RedisConstant.REDIS_KEY_ROLEMENU_PREFIX, MyUtil.getValue(user.get("userAccount")));
      redisMyClient.del(roleMenuKey);
    });

  }

  /**
   * <p>todo 查询已授权菜单</p>
   * @param: roleId
   * @return: java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/30 20:12
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/30    andy.ten        v1.0.1             init
   */
  @Override
  public List<Map<String, Object>> searchAuthGrantMenus(Long roleId)
  {
    return sysRoleMenuMapper.searchAuthGrantMenus(roleId);
  }
}
